import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

/**
 * Object defining all aspects of the html pages to be produced
 * 
 * @author tomalteman
 *
 */
public class page {
	private ArrayList<article> news;
	private ArrayList<article> sport;
	private ArrayList<article> biz;
	private ArrayList<article> ent;
	private ArrayList<article> noclass;
	private ArrayList<article> unknown;
	private int errors;
	private int total;		
	private boolean extra;
	private ArrayList<String> found;
	
	
	
	
	/////////////////////////
	////EDITABLE VALUES
	/////////////////////////
	
	//Flag to indicate whether using classifier or not
	private boolean classify = true;
	
	private int debug = 0;
	private int minSize = 3;
	
	private boolean doGeo = true;
	private double geoStart = 0.2;
	private double geoStep = 0.1;
	private double geoEnd = 1.0;
	private locList uk;
	
	
	public page()
	{
		noclass = new ArrayList<article>();
		news = new ArrayList<article>();
		sport = new ArrayList<article>();
		biz = new ArrayList<article>();
		ent = new ArrayList<article>();
		found = new ArrayList<String>();
		unknown = new ArrayList<article>();
		errors = 0;
		total=0;
		extra=false;
		
		uk = new locList();
		uk.load("locations/uk.txt");
	}
	
	public page(int ms)
	{
		noclass = new ArrayList<article>();
		news = new ArrayList<article>();
		sport = new ArrayList<article>();
		biz = new ArrayList<article>();
		ent = new ArrayList<article>();
		found = new ArrayList<String>();
		unknown = new ArrayList<article>();
		errors = 0;
		total=0;
		extra=false;
		
		uk = new locList();
		uk.load("locations/uk.txt");
		
		minSize = ms;
	}
	
	public void build(String q, String country)
	{
		double geo = geoStart;
		
		//Get articles for this query
		getArts(q,country);
		
		//Spread area of search using locList
		if(doGeo && country.equals("uk") && (minSize>0))
		{
			extra = true;
			ArrayList<location> input;
			while(!isFilled() && (geo <= geoEnd))
			{
				if(debug==3) System.out.println("GEO "+ geo);
				input = uk.getNeighbours(q, geo);
				
				for(int i=0;i<input.size();i++)
				{
					unknown = new ArrayList<article>();
					System.out.println("EXTEND SEARCH TO "+input.get(i).name);
					System.out.println();
					getArts(input.get(i).name,country);
					
					//If each section if filled then break
					if(isFilled()) break;
				}
				
				geo = geo + geoStep;
			}
		}
		
		if(debug==2) 
		{
			System.out.println("FINAL");
			System.out.println("Size of NEWS is "+news.size());
			System.out.println("Size of SPORT is "+sport.size());
			System.out.println("Size of BUSINESS is "+biz.size());
			System.out.println("Size of ENT is "+ent.size());
		}
		
		//Get local Ranking
		//	news = Classifier.doLocRank(news, q.toLowerCase());
		news = Classifier.localClassify(news, q.toLowerCase());
		Collections.sort(news);
		
		//sport = Classifier.doLocRank(sport, q.toLowerCase());
		sport = Classifier.localClassify(sport, q.toLowerCase());
		Collections.sort(sport);
		
		//ent = Classifier.doLocRank(ent, q.toLowerCase());
		ent = Classifier.localClassify(ent, q.toLowerCase());
		Collections.sort(ent);
		
		//biz = Classifier.doLocRank(biz, q.toLowerCase());
		biz = Classifier.localClassify(biz, q.toLowerCase());
		Collections.sort(biz);
		
		//biz = Classifier.doLocRank(biz, q.toLowerCase());
		noclass = Classifier.localClassify(noclass, q.toLowerCase());
		Collections.sort(noclass);
		
		//Write pages
		if(!classify) writePage.write(q,unknown,"news");
		else writePage.write(q,news,"news");
		writePage.write(q,sport,"sport");
		writePage.write(q,biz,"biz");
		writePage.write(q,ent,"ent");
		//writePage.write(q,noclass,"noclass");
		
		//Print total
		System.out.println("Errors are " + errors);
		System.out.println("Total is " + total);
	}
	
	/**
	 * See if every section has at least minSize amount of articles
	 * @return
	 */
	private boolean isFilled()
	{
		//System.out.println("min size is "+minSize);
		//System.out.println("biz size is "+biz.size());
		if((news.size() < minSize) || (sport.size() < minSize) || (biz.size() < minSize) || (ent.size() < minSize)) return false;
		return true;
	}
	
	/**
	 * Get articles for a given query
	 * @param q
	 * @param country
	 */
	private void getArts(String q, String country)
	{
		String[] query = getQuery.getQuery(q,country);
		
		//Sort results for each query
		feedParse reader = new feedParse();
		System.out.println("DO 1: " + query[0]);
		sort(reader.parsePage(query[0]));
		System.out.println("DO 2: " + query[1]);
		sort(reader.parsePage(query[1]));
		System.out.println("DO 3: " + query[2]);
		sort(reader.parsePage(query[2]));
		System.out.println("DO 4: " + query[3]);
		sort(reader.parsePage(query[3]));
		System.out.println("DO 5: " + query[4]);
		sort(reader.parsePage(query[4]));
		
		if(classify)
			{
				System.out.println();
				System.out.println("CLASSIFYING UNKNOWN");
				labelSort(Classifier.classify(unknown));
			}
		
		if(debug==2) 
		{
			System.out.println("Size of NEWS is "+news.size());
			System.out.println("Size of SPORT is "+sport.size());
			System.out.println("Size of BUSINESS is "+biz.size());
			System.out.println("Size of ENT is "+ent.size());
			System.out.println("Using "+(news.size()+sport.size()+biz.size()+ent.size()));
		}
	}
	
	private void labelSort(ArrayList<article> arts)
	{
		article art;
		for(int i=0;i<arts.size();i++)
		{
			art = arts.get(i);
			switch (art.category) {
				case -1: if(!extra || (noclass.size() < minSize)) news.add(art); break;
				case 1: if(!extra || (news.size() < minSize)) news.add(art); break;
				case 2: if(!extra || (biz.size() < minSize)) biz.add(art); break;
				case 3: if(!extra || (ent.size() < minSize)) ent.add(art); break;
				case 4: if(!extra || (sport.size() < minSize)) sport.add(art); break;
				default: if(!extra || (noclass.size() < minSize)) news.add(art); break;
			}
		}
	}
	
	/**
	 * Gets list of articles from feed and sorts them
	 * @param art
	 */
	private void sort(ArrayList<article> arts)
	{
		pageParser p = new pageParser();
		article art;
		
		for(int i=0;i<arts.size();i++)
		{
			art = arts.get(i);
			
			if(!found.contains(art.getTitle()))
			{
				if(art.checkArt() == 1)
				{
					total++;
					
					
					//Get text for an article
					art.setText(p.getText(art.getLink(), art.getDescription()));
					
					if(debug==1) System.out.println("TEXT FOR ART IS "+ art.getText());
					
					if(art.getText().equals("connectionerror")) parseErr(art,"CANNOT CONNECT",false);
					//Check whether length of text is greater than length of description for validity
					else if((art.getText()).length() <= (art.getDescription()).length())
						{
							parseErr(art,"LENGTH ERR",true);
							//art.setDescription("");
							//classArt(art);
						}
					else classArt(art);
				}
				//else parseErr(art,"ART CHECK ERR",false);
			}
			
		}
	}
	
	/**
	 * Simply check link to see what type of article it is
	 * 
	 * @param art
	 */
	private void classArt(article art)
	{
		//If its found already ignore it
		if(found.contains(art.getTitle())) return;
		
		String link = (art.getLink()).toLowerCase();
		
		if((link.indexOf("/sport/") > -1)&&!extra) sport.add(art);
		else if((link.indexOf("/business/") > -1)&&!extra) biz.add(art);
		else if((link.indexOf("/entertainment/") > -1)&&!extra) ent.add(art);
		else unknown.add(art);
		
		//Add title to list of article found
		found.add(art.getTitle());
	}
	
	/**
	 * Printing badly parsed articles
	 * Boolean avoid indicates whether error is avoidable
	 * @param art
	 */
	private void parseErr(article art,String reason, boolean avoid)
	{
		if(avoid) errors++;
		System.out.println("CANNOT PARSE: "+art.getTitle()+ " DUE TO "+ reason);
		System.out.println("LINK IS: "+art.getLink());
		System.out.println("SOURCE IS " + art.getSource());
		System.out.println("DESCRIPTION IS: "+art.getDescription());
		System.out.println("TEXT IS: "+art.getText());
		System.out.println("Errors are " + errors);
		System.out.println("Total is " + total);
		
		found.add(art.getTitle());
	}
	
	/**
	 * Acquires test set
	 * @param q
	 */
	private void storeTest(String q)
	{
		String country = "uk";
		
		classify = false;
		doGeo = false;
		
		//Read in found file
		ArrayList<String> f = TFile.read(new File("training/test/found"));
		
		//Set size to whatever num gives unique
		int size = Integer.parseInt(f.get(0));
		
		//Set found list
		f.remove(0);
		found= f;
		
		getArts(q, country);
		
		//Get current size of test directory
		//int size = new File("training/test/text/").listFiles().length;
		
		
		article art;
		
		if(debug==3) 
		{
			System.out.println("Size of NEWS is "+news.size());
			System.out.println("Size of SPORT is "+sport.size());
			System.out.println("Size of BUSINESS is "+biz.size());
			System.out.println("Size of ENT is "+ent.size());
			System.out.println("Size of UNKNOWN is "+unknown.size());
		}
		
		//Write to directory
		for(int i=0;i<unknown.size();i++)
			{
				//System.out.println("Writing "+unknown.get(i).getTitle());
				TFile.writeArt(new File("training/test/text/"+q+"-unknown-"+size), unknown.get(i));
				size++;
			}
		for(int i=0;i<sport.size();i++)
			{
				art = sport.get(i);
				art.category = 4;
				TFile.writeArt(new File("training/test/text/"+q+"-sport-"+size), art);
				size++;
			}
		for(int i=0;i<ent.size();i++)
		{
			art = ent.get(i);
			art.category = 3;
			TFile.writeArt(new File("training/test/text/"+q+"-ent-"+size), art);
			size++;
		}
		for(int i=0;i<biz.size();i++)
		{
			art = biz.get(i);
			art.category = 2;
			TFile.writeArt(new File("training/test/text/"+q+"-biz-"+size), art);
			size++;
		}
		
		//Store found list
		found.add(0,Integer.toString(size));
		TFile.write(new File("training/test/found"), found);
	}
	
	public static void main(String[] args)
	{
		String[] q = {"bristol","abergavenny","durham","london","manchester"};
		
		page p = new page();
		for(int i=0;i<q.length;i++) 
			{
				p = new page();
				p.storeTest(q[i]);
			}
	}
}
